/**
 * Main simulation/prediction (that's why Delphi) module.
 *
 * \file delphi.cpp
 * \author tomby
 * \date 04-01-2009
 **/

/*  Copyright (C) 2009  Tomas 'tomby' Bily

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include <iostream>
#include "dbc-sys.hpp"


using namespace dbc;

static void
print_boot_text ()
{
  std::cout << "dbc-vbl DELPHI PREDICTOR ver. 0.1 \n";
  std::cout << "\n";
  std::cout << "\n\
	dbc-vbl DELPHI PREDICTOR Copyright (C) 2009  dbc-vbl team\n\
	this program comes with ABSOLUTELY NO WARRANTY.\n\
	This is free software, and you are welcome to redistribute it\n\
	under certain conditions; for details see license.\n\n";
}

typedef AdaptiveArray <aa_equal_distr_constr<int, 3> > AA;
typedef blitz::TinyVector<int, 3> IndexType;
typedef blitz::TinyVector<int, 3> IT;
typedef AANeighbourNodeIterator<AA> NI;
typedef blitz::RectDomain<3> RD;
typedef AANeighbourIterator<AA> NeI;
typedef HyperCubeBorderIterator<3> HI;
typedef AAVirtNeighbourIterator<AA> VNeI;
typedef AA::cell_index CI;

static void
print_idx (IndexType& pos)
{
  printf ("%d %d %d\n", pos [0], pos [1], pos [2]);
}

static void
print_a (AA::NumericArrayType* na)
{
  for (AA::NumericArrayType::iterator it1 = na->begin (); it1 != na->end (); ++it1)
    {
      AA::IndexType pos1 = it1.position ();
      printf ("  %d %d %d  %d\n", pos1 [0], pos1 [1], pos1 [2], *it1); 
    }
} 

static void
print_aa (AA& a)
{
  for (AA::node_iterator it = a.begin (); it != a.end (); ++it)
    {
      AA::IndexType pos = it.position ();
      if (!it.level ())
	printf ("%d %d %d  %d\n", pos [0], pos [1], pos [2], it.data ());
      else
	{
	  printf ("%d %d %d\n", pos [0], pos [1], pos [2]);
	  print_a (*it);
	}
    }
  printf ("\n");
}

static void
test ()
{
  AA::IndexType size ((3<<4) - 1, (3<<4) - 1, (3<<4) - 1);
  AA a (size, 1);
  
  print_aa (a);

  AA::node_iterator it = a.begin ();
  ++it;
  it.refine ();
  *(*it) = 2;
  (*(*it)) (0, 0, 0) = 3;
  it.refine ();
  print_aa (a);
  //it.coarse ();
  coarse_if_possible<AA> (it);
  print_aa (a);
  size = 0;
  printf ("%d\n", a (size));

  if (blitz::all ((*(*it)) != 4))
    printf ("YES!!!\n");
  else
    printf ("NO!!!\n");

  AA::NumericArrayType nat (*(it.level_iter (1)));
  print_a (&nat);

  RD rad (IT (-2), IT (2));
  NI nit (it, rad);
  NI nite (it, rad, true);
  printf ("neighbours of ");
  
  print_idx (it.position ());
  for (; nit != nite; ++nit)
    print_idx (nit.rel_position ());

  it = a.begin ();
  it.refine ();
  IT i0 (0);
  NeI neit (it, i0, rad);
  for (; !neit.end_p (); ++neit)
    {
      printf ("global: ");
      IT pos (neit.global_position ());
      print_idx (pos);
      printf ("local: ");
      pos = neit.local_position ();
      print_idx (pos);
      printf ("relative: ");
      pos = neit.rel_position ();
      print_idx (pos);
    }

  AA::Node n (4);
  IT i1 (2);
  VNeI vneit (it, &n, i1, rad);

  for (; !vneit.end_p (); ++vneit)
    {
      printf ("global: ");
      IT pos (vneit.global_position ());
      print_idx (pos);
      printf ("local: ");
      pos = vneit.local_position ();
      print_idx (pos);
    }
#if 1
  {
    IT s (18);
    HI begin (s);
    HI end (s, true);
    IT ip (1);

    aa_fill<AA, HI> (&a, begin, end, ip, 7);
    print_aa (a);
  }
#endif
  {
    std::vector<CI> n;
    CI c (IT (0), IT (0));
    
    aa_sphere_neighbour<AA> (n, &a, c, 4);

    for (std::vector<CI>::iterator i = n.begin (); i != n.end (); ++i)
      {
	CI p (*i);

	printf ("global: ");
	print_idx (p.node ());
	printf ("  local: ");
	print_idx (p.val ());
      }
  }

  AACacheIterator<NeI> cache (&a, rad, 0);
}

/** 
 * This is entry into Delphi.
 * Before you enter, read the sign: "gnothi seauton" ;)
 **/

int
main (int argc, char** argv)
{
  print_boot_text ();

  test ();

  return 0;
}
